package warehouse;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import scheduler.HospitalDate;
import scheduler.TimeLord;
import system.Campus;
import warehouse.item.ActivatedCarbonType;
import warehouse.item.AsprinType;
import warehouse.item.MealType;
import warehouse.item.MiscType;
import warehouse.item.PlasterType;
import warehouse.item.SleepingTabletsType;
import warehouse.item.VitaminType;
import warehouse.item.WarehouseItemType;
import warehouse.orderstrat.MedicationOrderStrategy;
import warehouse.orderstrat.PatientMealStrategy;
import warehouse.orderstrat.PlasterOrderStrategy;
import warehouse.stock.ExpiredItemRemover;
import warehouse.stock.StockProvider;
import exceptions.InvalidWarehouseItemException;
import exceptions.WarehouseOverCapacityException;

/**
 * Initialises new warehouses.
 */
public class NormalWarehouseBuilder implements WarehouseBuilder
{
	private Campus campus_;
	private TimeLord timeLord_;

	public class WarehouseSet
	{
		public WarehouseSet(Warehouse w, StockProvider prov) {
			this.warehouse = w;
			this.provider = prov;
		}

		public final Warehouse warehouse;
		public final StockProvider provider;
	}

	private Map<WarehouseItemType, Integer> maxCountMap() {
		Map<WarehouseItemType, Integer> rv = new HashMap<WarehouseItemType, Integer>();
		rv.put(new AsprinType(), 10);
		rv.put(new ActivatedCarbonType(), 10);
		rv.put(new MealType(), 120);
		rv.put(new MiscType(), 10);
		rv.put(new PlasterType(), 8);
		rv.put(new SleepingTabletsType(), 10);
		rv.put(new VitaminType(), 10);

		return rv;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see warehouse.WarehouseBuilder#create()
	 */
	@Override
	public WarehouseSet create(Campus campus) {
		campus_ = campus;
		timeLord_ = campus.getHospital().getTimeKeeper();
		Warehouse w = new Warehouse(campus_);
		for (Entry<WarehouseItemType, Integer> entry : maxCountMap().entrySet())
			try {
				w.setMaxCount(entry.getKey(), entry.getValue());
				for (int i = 0; i < entry.getValue(); i++)
					try {
						w.add(entry.getKey(), new HospitalDate(campus.getSystemTime().getSystemTime()
								.getTimeSinceStart()
								+ entry.getKey().getTimeToLive()));
					} catch (WarehouseOverCapacityException e) {

					}
			} catch (InvalidWarehouseItemException e) {
				throw new Error("Problem while building standard warehouse");
			}
		StockProvider prov = new StockProvider();
		addOderStrategies(w, prov);
		w.addObserver(new ExpiredItemRemover(w, timeLord_));
		timeLord_.addObserver(prov);
		return new WarehouseSet(w, prov);
	}

	/**
	 * Adds order strategies as observers to the warehouse.
	 */
	private void addOderStrategies(Warehouse w, StockProvider prov) {
		w.addObserver(new MedicationOrderStrategy((new AsprinType()), w, prov, timeLord_));
		w.addObserver(new MedicationOrderStrategy((new ActivatedCarbonType()), w, prov, timeLord_));
		w.addObserver(new MedicationOrderStrategy((new MiscType()), w, prov, timeLord_));
		w.addObserver(new MedicationOrderStrategy((new SleepingTabletsType()), w, prov, timeLord_));
		w.addObserver(new MedicationOrderStrategy((new VitaminType()), w, prov, timeLord_));
		w.addObserver(new PatientMealStrategy(new MealType(), w, prov, timeLord_, campus_.getHospital()
				.getPatientFileManager()));
		w.addObserver(new PlasterOrderStrategy(w, prov, timeLord_));
	}
}
